package com.flow.framework.common.json.deserializer;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.deser.std.StringDeserializer;

import java.io.IOException;

/**
 * 允许将任何json对象中的json对象反序列化成对象中的字符串
 *
 * @author luoguopiao
 * @version 0.0.1
 * @date 2022/1/2
 */
@JacksonStdImpl
public class ObjectToStringDeserializer extends StringDeserializer {
    @Override
    public String deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException {
        // 如果是string，则直接获取text返回
        if (jsonParser.hasToken(JsonToken.VALUE_STRING)) {
            return jsonParser.getText();
        }
        JsonToken jsonToken = jsonParser.currentToken();

        // [databind#381]
        // 如果是数组，则反序列化成数组字符串
        if (jsonToken == JsonToken.START_ARRAY) {
            return _deserializeFromArray(jsonParser, context);
        }

        // need to gracefully handle byte[] data, as base64
        // 如果是内置对象，则分情况考虑
        if (jsonToken == JsonToken.VALUE_EMBEDDED_OBJECT) {
            Object object = jsonParser.getEmbeddedObject();
            if (object == null) {
                return null;
            }
            if (object instanceof byte[]) {
                return context.getBase64Variant().encode((byte[]) object, false);
            }

            // otherwise, try conversion using toString()...
            // 直接将内置对象toString返回
            return object.toString();
        }
        // allow coercions for other scalar types
        // 17-Jan-2018, tatu: Related to [databind#1853] avoid FIELD_NAME by ensuring it's
        //   "real" scalar
        if (jsonToken.isScalarValue()) {
            String text = jsonParser.getValueAsString();
            if (text != null) {
                return text;
            }
        }

        // 其他情况则直接读取json并将该json变成json字符串返回
        // 如果不变成字符串返回，则会报错：com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.lang.String` from Object value (token `JsonToken.START_OBJECT`)
        return context.readTree(jsonParser).toString();
    }
}
